﻿using JetBrains.ReSharper.Daemon.CSharp.Stages;
using JetBrains.ReSharper.Daemon.Stages;
using JetBrains.ReSharper.Daemon.Stages.Dispatcher;
using JetBrains.ReSharper.Psi;
using JetBrains.ReSharper.Psi.CSharp.Tree;
using MugenMvvmToolkit.ReSharper.Highlighting;
using MugenMvvmToolkit.ReSharper.Infrastructure;

namespace MugenMvvmToolkit.ReSharper.ViewModels.Analyzers
{
    [ElementProblemAnalyzer(new[] { typeof(IPropertyDeclaration) },
        HighlightingTypes = new[] { typeof(MismatchModelPropertyNameHighlighting) })]
    public class MismatchModelPropertyNameAnalyzer : ElementProblemAnalyzerBase<IPropertyDeclaration>
    {
        #region Overrides of ElementProblemAnalyzerBase<IPropertyDeclaration>

        protected override void Run(IPropertyDeclaration element, ElementProblemAnalyzerData data,
            IHighlightingConsumer consumer)
        {
            if (element.IsAuto)
                return;
            var @class = element.FindParent<IClassLikeDeclaration>();
            if (@class == null || !@class.IsOfType(TypeProvider.ViewModelInterface))
                return;
            IAccessorDeclaration getter = element
                .AccessorDeclarations
                .FirstOrDefault(declaration => declaration.Kind == AccessorKind.GETTER);
            if (getter == null)
                return;
            getter.ProcessDescendantsForResolve(
                new OneActionProcessor(node =>
                {
                    var returnStatement = node as IReturnStatement;
                    if (returnStatement != null)
                        Process(returnStatement, element, @class, consumer);
                }, node => true));
        }

        #endregion

        #region Methods

        private void Process(IReturnStatement returnStatement, IPropertyDeclaration element,
            IClassLikeDeclaration @class,
            IHighlightingConsumer consumer)
        {
            if (returnStatement == null)
                return;
            var referenceExpression = returnStatement.Value as IReferenceExpression;
            var entityProperty = referenceExpression.GetQualifierExpressionDeclaredElement<IProperty>();
            if (entityProperty == null || entityProperty.ShortName != PropertyNameConstants.EdiatableViewModelEntity)
                return;

            var modelProperty = referenceExpression.GetDeclaredElement<IProperty>();
            if (modelProperty == null || modelProperty.ShortName == element.DeclaredName)
                return;

            foreach (IAttribute attribute in element.Attributes)
            {
                if (attribute.IsOfType(TypeProvider.IgnorePropertyAttribute))
                    return;
                var literalExpression = ToolkitExtensions.TryGetModelPropertyAttributeValue(attribute, TypeProvider);
                if (literalExpression == null)
                    continue;
                var s = literalExpression.ConstantValue.Value as string;
                if (modelProperty.ShortName == s)
                    return;
            }
            consumer.AddHighlighting(new MismatchModelPropertyNameHighlighting(@class, element, modelProperty));
        }

        #endregion
    }
}